﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using WindowsFormsApplication1;

namespace debugger
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        public Form1 mainForm;

        private void Form2_Load(object sender, EventArgs e)
        {
        }
        public class MemPage
        {
            public int page;
            public uint[] data = new uint[256];
        }


        MemPage[] pages = new MemPage[1+1];

        private void button1_Click(object sender, EventArgs e)
        {
            uint ret;
            uint val;
            uint err = 0;
            Random r = new Random();


            if (false)
            {
                byte[] temp = new byte[4];
                for (int i = 0; i < 100000; i++)
                {
                    r.NextBytes(temp);
                    val = 0;
                    val |= (uint)temp[0] << 0;
                    val |= (uint)temp[1] << 8;
                    val |= (uint)temp[2] << 16;
                    val |= (uint)temp[3] << 24;
                    ret = mainForm.sendCmdRet(0x23, val);
                    if (val != ret)
                    {
                        err++;
                    }
                    
                    
                    r.NextBytes(temp);
                    val = 0;
                    val |= (uint)temp[0] << 0;
                    val |= (uint)temp[1] << 8;
                    val |= (uint)temp[2] << 16;
                    val |= (uint)temp[3] << 24;
                    ret = mainForm.sendCmdRet(0x16, val);
                    ret = mainForm.sendCmdRet(0x76, 0);
                    if (val != ret)
                    {
                        err++;
                    }
                    //
                    //r.NextBytes(temp);
                    //val = 0;
                    //val |= (uint)temp[0] << 0;
                    //val |= (uint)temp[1] << 8;
                    //val |= (uint)temp[2] << 16;
                    //val |= (uint)temp[3] << 24;
                    //mainForm.sendCmd(0x17, val);
                    //ret = mainForm.sendCmdRet(0x77, 0);
                    //if (val != ret)
                    //{
                    //    err++;
                    //}
                }
                return;
            }

            for (int i = 0; i < 1024; i++)
            {
                mybuff[i * 2] = (byte)(i & 0xFF);
                mybuff[i * 2 + 1] = (byte)((i >> 8) & 0xFF);
            }
            r.NextBytes(mybuff);

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 2048; i++)
            {
                if ((i & 15) == 0)
                {
                    sb.AppendLine();
                }
                sb.Append(Util.getHex2(mybuff[i]) + " ");
            }
            sb.AppendLine();
            textBox1.Text = sb.ToString();
            /*StringBuilder sb = new StringBuilder();
                        Random r = new Random();
                        mainForm.clearBuff();

                        mainForm.sendCmd(Form1.NOCACHE1);//nocache

                        for (int j = 0; j < pages.Length; j++)
                        {
                            pages[j] = new MemPage();
                            bool dup = true;
                            while (dup)
                            {
                                pages[j].page = r.Next(0x02000000 >> 10);
                                bool flg = true;
                                for (int i = 0; i < j - 1; i++)
                                {
                                    if (pages[j].page == pages[i].page)
                                    {
                                        flg = false;
                                    }
                                }
                                if (flg)
                                {
                                    dup = false;
                                }
                            }
                            for (int i = 0; i < 1024; i += 4)
                            {
                                pages[j].data[i >> 2] = (uint)r.Next();
                            }

                        }

                        this.textBox1.Text = "";
                        for (int j = 0; j < pages.Length; j++)
                        {
                            int pageA = pages[j].page;
                            uint[] dataA = pages[j].data;
                            bool err = true;
                            while (err)
                            {
                                bool flg = true;
                                try
                                {
                                    mainForm.clearBuff();

                                    for (int i = 0; i < 1024; i += 4)
                                    {
                                        uint addr = (uint)((pageA << 10) + i);
                                        mainForm.setmem(addr, dataA[i >> 2]);
                                    }
                                    for (int i = 0; i < 1024; i += 4)
                                    {
                                        uint addr = (uint)((pageA << 10) + i);
                                        uint val = mainForm.getmem(addr, null);
                                        if (val != dataA[i >> 2])
                                        {
                                            flg = false;
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    flg = false;
                                }
                                if (flg)
                                {
                                    err = false;
                                }
                                else
                                {
                                    this.textBox1.Text += "err";
                                }
                            }
                            this.textBox1.Text += "," + j;
                            Application.DoEvents();
                        }

                        mainForm.sendCmd(Form1.NOCACHE0);//nocache

                        //MessageBox.Show("ok");
                        */
        }

        private void confirm(MemPage page, int offset, StringBuilder sb)
        {
            int pageA = page.page;
            uint[] dataA = page.data;

            uint addr = (uint)((pageA << 10) + offset);
            uint val = mainForm.getmem(addr, null);
            if (sb != null)
            {
                if (val != dataA[offset >> 2])
                {
                    sb.Append(" access time:");
                    sb.Append(mainForm.getAccessTime());
                    sb.Append("addr:" + Util.getHex8(addr) + ",data:" + Util.getHex8(dataA[offset >> 2]) + ",mem:" + Util.getHex8(val));
                    sb.AppendLine();
                }
            }
        }

        byte[] mybuff = new byte[2048];

        byte[] mybuff2 = new byte[2048];
        private void button3_Click(object sender, EventArgs e)
        {
            /*
            uint ret;
            uint val;
            uint err = 0;
            Random r = new Random();

            //read
            if (true)
            {
                mainForm.receive(mybuff2);
            }
            else
            {
                for (uint i = 0; i < 512; i++)
                {
                    mainForm.getReg(i << 2, mybuff2, i << 2);
                }
            }
            StringBuilder sb = new StringBuilder();

            err = 0;

            sb.AppendLine();

            if (true)
            {
                for (int i = 0; i < 2048; i++)
                {
                    if (mybuff[i] != mybuff2[i])
                    {
                        err++;
                    }
                    if ((i & 15) == 0)
                    {
                        sb.AppendLine();
                    }
                    sb.Append(Util.getHex2(mybuff2[i]) + " ");
                }
            }

            textBox1.Text = err + " " + sb.ToString();
            //ret = sendCmdRet(0x32, 0x12345678);
            //
            //ret = sendCmdRet(0x30, 0x12);
            //
            //ret = sendCmdRet(0x31, 0x23);

            
            StringBuilder sb = new StringBuilder();
            Random r = new Random();
            mainForm.clearBuff();

            wbprep(sb, r);

            for (int j = 0; j < 1; j++)
            {
                MemPage pageA = pages[j];
                for (int i = 0; i < 512; i++)
                {
                    confirm(pageA, r.Next(128) << 2, sb);
                }

                for (int i = 0; i < 128; i++)
                {
                    confirm(pageA, i << 2, sb);
                }
                this.Text = ""+j;
                Application.DoEvents();
            }


            for (int i = 0; i < 1; i++)
            {
                uint life;
                uint addr;
                string invalid;
                string dirty;
                mainForm.getCacheDebugData(i, null, out addr, out life, out invalid, out dirty);
                if (life != i) {
                    this.textBox1.Text = "err1";
                    return;
                }
            }

            for (int j = 0; j < 255; j++)
            {
                confirm(pages[1], j << 2, null);
            }

            uint cache_life_count = mainForm.sendCmdRet(Form1.GET_CACHE_LIFE_COUNT);//cache life count
            if (cache_life_count != 0) {
                this.textBox1.Text = "err2";
                return;
            }

            confirm(pages[1], 0, sb);

            uint flush_count = mainForm.getmem(Form1.CACHE_CTL, null);//flush count
            if (flush_count != 1)
            {
                this.textBox1.Text = "err3";
                return;
            }

            mainForm.sendCmd(Form1.NOCACHE1);//nocache
            for (int i = 0; i < 256; i++)
            {
                confirm(pages[0], i << 2, sb);
            }
            mainForm.sendCmd(Form1.NOCACHE0);//nocache

            sb.AppendLine("end");
            this.textBox1.Text = sb.ToString();
            */
        }

        private void button2_Click(object sender, EventArgs e)
        {
            /*
            uint ret;
            uint val;
            uint err = 0;
            Random r = new Random();

            //write
            //if (true)
            //{
            mainForm.send(mybuff);
            //}
            //else
            //{
            //    for (uint i = 0; i < 512; i++)
            //    {
            //        mainForm.setReg(i << 2, mybuff, i << 2);
            //    }
            //}
            
            
            StringBuilder sb = new StringBuilder();
            Random r = new Random();
            mainForm.clearBuff();

            mainForm.sendCmd(Form1.NOCACHE0);//nocache

            int count = (int.Parse(this.textBox2.Text)*1024)/4;

            uint[] data = new uint[count];

            for (uint i = 0; i < count; i++)
            {
                uint val = (uint)r.Next();
                mainForm.setmem(i*4,val);
                //mainForm.getstatus();
                //Application.DoEvents();
                data[i] = val;
                if ((i & 255) == 0) {
                    this.Text = "" + (i * 4);
                    Application.DoEvents();
                }
            }
            int err = 0;

            //mainForm.portWriteNew(0x69, 1);//nocache
            //
            //for (uint i = 0; i < count; i++)
            //{
            //    uint val = mainForm.getmem(i * 4, null);
            //    if (data[i] != val) {
            //        sb.AppendLine("a"+Util.getHex8(i * 4)+","+Util.getHex8(data[i])+","+Util.getHex8(val));
            //        err++;
            //    }
            //    if ((i & 255) == 0)
            //    {
            //        this.Text = "" + (i * 4);
            //        Application.DoEvents();
            //    }
            //}
            //
            //mainForm.portWriteNew(0x69, 0);//nocache


            err = 0;
            for (uint i = 0; i < count; i++)
            {
                uint val = mainForm.getmem(i * 4, null);
                //mainForm.getstatus();
                //Application.DoEvents();
                if (data[i] != val)
                {
                    sb.AppendLine("b" + Util.getHex8(i * 4) + "," + Util.getHex8(data[i]) + "," + Util.getHex8(val));
                    err++;
                }
                if ((i & 255) == 0)
                {
                    this.Text = "" + (i * 4);
                    Application.DoEvents();
                }
            }

            this.textBox1.Text = sb.ToString();

            */
        }

        private void button4_Click(object sender, EventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            Random r = new Random();
            mainForm.clearBuff();

            int[] points = new int[16];
            for (int i = 0; i < 16; i++)
            {
                points[i] = r.Next(256) << 2;
            }

            for (int i = 0; i < 16; i++)
            {
                confirm(pages[i], points[i], sb);
            }
            sb.AppendLine("------------1");
            {
                int j = 16;
                MemPage pageA = pages[j];

                for (int i = 0; i < 1024; i += 4)
                {
                    confirm(pageA, i, sb);
                }
            }
            sb.AppendLine("------------2");

            for (int i = 0; i < 16; i++)
            {
                int j = r.Next(256) << 2;
                confirm(pages[i], points[i], sb);
            }

            sb.AppendLine("------------3");

            for (int i = 0; i < 16; i++)
            {
                int j = r.Next(256) << 2;
                confirm(pages[i], 0, sb);
            }

            sb.AppendLine("end");
            this.textBox1.Text = sb.ToString();

        }

        private void wbprep(StringBuilder sb, Random r)
        {

            int[] points = new int[192];

            for (int j = 0; j < points.Length; j++)
            {
                bool dup = true;
                while (dup)
                {
                    points[j] = r.Next(256) << 2;
                    bool flg = true;
                    for (int i = 0; i < j - 1; i++)
                    {
                        if (points[j] == points[i])
                        {
                            flg = false;
                        }
                    }
                    if (flg)
                    {
                        dup = false;
                    }
                }
            }

            int[] bytePoses = new int[64];
            for (int j = 0; j < bytePoses.Length; j++)
            {
                bytePoses[j] = r.Next(4);
            }

            //targetpage,读取一部分，写入一部分   部分valid，部分dirty
            for (int i = 0; i < 32; i++)
            {
                confirm(pages[0], points[i], sb);
            }
            //sb.AppendLine("------------p1");

            for (int i = 64; i < 128; i++)
            {
                int pageA = pages[0].page;
                uint[] dataA = pages[0].data;
                uint val = (uint)r.Next();
                int offset = points[i];
                uint addr = (uint)((pageA << 10) + offset);
                dataA[offset >> 2] = val;
                mainForm.setmem(addr, val);
                //sb.AppendLine("write addr:" + Util.getHex8(addr) + ",data:" + Util.getHex8(dataA[offset >> 2]));

            }
            //sb.AppendLine("------------p2");
            for (int i = 128; i < 192; i++)
            {
                if (i < 160)
                {
                    confirm(pages[0], points[i], sb);
                }
                int bytePos = bytePoses[i - 128];
                int pageA = pages[0].page;
                uint[] dataA = pages[0].data;
                int offset = points[i];
                uint addr = (uint)((pageA << 10) + offset);

                uint val = (uint)r.Next();

                throw new Exception("TODO");//mainForm.writeByteEnable(1 << bytePos);
                uint mask = ((uint)(0x0FF)) << (bytePos * 8);
                uint maskrev = ~mask;
                val &= mask;
                dataA[offset >> 2] &= maskrev;
                dataA[offset >> 2] |= val;
                mainForm.setmem(addr, val);
                //sb.AppendLine("write addr:" + Util.getHex8(addr) + ",data:" + Util.getHex8(val));
            }
            throw new Exception("TODO");//mainForm.writeByteEnable(15);

            for (int i = 0; i < 256; i++)
            {
                int pageA = pages[0].page;
                uint[] dataA = pages[0].data;
                uint addr = 0;
                int offset = 0;
                bool found = false;
                for (int j = 0; j < points.Length; j++)
                {
                    if ((points[j] >> 2) == i)
                    {
                        offset = points[j];
                        addr = (uint)((pageA << 10) + offset);
                        found = true;
                    }
                }
                if (found)
                {
                    //sb.AppendLine("writed addr:" + Util.getHex8(addr) + ",data:" + Util.getHex8(dataA[offset >> 2]));
                }
                else
                {
                    //sb.AppendLine("writed addr:" + Util.getHex8(addr) + ",data:");
                }

            }

            {
                MemPage pageA = pages[0];
                //sb.AppendLine("------------p3");
                for (int i = 64; i < 128; i++)
                {
                    confirm(pageA, points[i], sb);
                }
                //sb.AppendLine("------------p4");
                for (int i = 128; i < 160; i++)
                {
                    confirm(pageA, points[i], sb);
                }
                //sb.AppendLine("------------p5");
                for (int i = 160; i < 192; i++)
                {
                    confirm(pageA, points[i], sb);
                }
            }
        }

        //写回：
        private void button5_Click(object sender, EventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            Random r = new Random();
            mainForm.clearBuff();

            for (uint shift = 0x00080000; shift < 0x00082000; shift += 0x400)
            {

                //00002000
                uint[] data = new uint[256];

                for (uint i = 0; i < 256; i++)
                {
                    uint val = (uint)r.Next();
                    data[i] = val;
                    mainForm.setmem(i * 4 + shift, val);
                }
                for (int i = 0; i < 16; i++)
                {
                    mainForm.setmem(0x00002000 + shift, 333);
                    mainForm.setmem(0x00004000 + shift, 123);
                    mainForm.setmem(0x00006000 + shift, 333);
                }

                for (int i = 0; i < 16; i++)
                {
                    mainForm.setmem(0x00008000 + shift, 0x333);
                }

                mainForm.sendCmd(Form1.NOCACHE1);//nocache

                int err = 0;
                for (uint i = 0; i < 256; i++)
                {
                    uint val = mainForm.getmem(i * 4 + shift, null);
                    if (data[i] != val)
                    {
                        err++;
                    }
                }


                mainForm.sendCmd(Form1.NOCACHE0);//nocache

            }
            sb.AppendLine("end");
            this.textBox1.Text = sb.ToString();

        }
        //switch back and check
        private void button6_Click(object sender, EventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            Random r = new Random();
            mainForm.clearBuff();


            for (int i = 0; i < 256; i++)
            {
                confirm(pages[0], i << 2, sb);
            }

            sb.AppendLine("end");
            this.textBox1.Text = sb.ToString();

        }

        private void button7_Click(object sender, EventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            Random r = new Random();
            mainForm.clearBuff();

            int count = (int.Parse(this.textBox2.Text) * 1024) / 4;

            uint[] data = new uint[count];
            mainForm.sendCmd(Form1.NOCACHE1);//nocache

            for (uint i = 0; i < count; i++)
            {
                uint val = (uint)r.Next();
                mainForm.setmem(i * 4, val);
                data[i] = val;
                if ((i & 255) == 0)
                {
                    this.Text = "" + (i * 4);
                    Application.DoEvents();
                }
            }

            mainForm.sendCmd(Form1.NOCACHE0);//nocache



            int err = 0;
            for (uint i = 0; i < count; i++)
            {
                uint val = mainForm.getmem(i * 4, null);
                if (data[i] != val)
                {
                    sb.AppendLine("a" + Util.getHex8(i * 4) + ",T:" + Util.getHex8(data[i]) + ",F:" + Util.getHex8(val));
                    err++;
                }
                if ((i & 255) == 0)
                {
                    this.Text = "" + (i * 4);
                    Application.DoEvents();
                }
            }


            this.textBox1.Text = sb.ToString();


        }

        int status = 0; // 0 write 1 read
        int page = 0;
        int count = 0;
        int totalpage = 0;
        uint[] data;

        private void button8_Click(object sender, EventArgs e)
        {
            totalpage = int.Parse(this.textBox2.Text);
            status = 0;
            page = 0;
            count = 0;
            data = new uint[totalpage * 0x100];

            Random r = new Random();
            mainForm.sendCmd(Form1.NOCACHE1);//nocache

            for (uint i = 0; i < count * 0x100; i++)
            {
                uint val = (uint)r.Next();
                data[i] = val;
            }
            this.textBox1.Text = "";
        }

        private void button9_Click(object sender, EventArgs e)
        {
            Random r = new Random();
            for (int i = 0; i < 1000000000; i++)
            {
                uint addr = (uint)(r.Next() & 0x3FFF);
                mainForm.getmem(addr, null, true);
                uint val = mainForm.sendCmdRet(Form1.GET_FLUSH_COUNT, null);
                if ((val & 0xF0000000) != 0)
                {
                    int v = 0;
                }
                if ((i & 0x1023) == 0)
                {
                    this.Text = i.ToString();
                }
            }
        }

        private void button4_Click_1(object sender, EventArgs e)
        {
            Random r = new Random();
            byte[] buff = new byte[4];
            int err = 0;
            for (int i = 0; i < 1000; i++)
            {
                r.NextBytes(buff);
                uint val = 0;
                val |= (uint)buff[0] << 0;
                val |= (uint)buff[1] << 8;
                val |= (uint)buff[2] << 16;
                val |= (uint)buff[3] << 24;
                int dist = r.Next(32);
                int dir = r.Next(2);

                mainForm.setmem(0x5C000000, val);//val
                mainForm.setmem(0x5C000004, (uint)dist);//val
                mainForm.setmem(0x5C000008, (uint)dir);//val
                uint val1 = mainForm.getmem(0x5C000000,null);
                uint val2 = mainForm.getmem(0x5C000004, null);
                if (val1 != val2) {
                    err++;
                }
            }
            textBox1.Text = err + "";
        }

    }
}
